C++复习 智能指针

  1. 智能指针
    1. C++ 标准库(STL)中
    2. C++ 98
    3. C++ 11
      1. shared_ptr
      2. weak_ptr
      3. unique_ptr
      4. auto_ptr
      5. auto_ptr 与 unique_ptr 比较
  2. 补充

现代 C++:一文读懂智能指针

智能指针

C++ 标准库(STL)中

头文件:#include <memory>

C++ 98

std::auto_ptr<std::string> ps (new std::string(str));

C++ 11

  1. shared_ptr
  2. unique_ptr
  3. weak_ptr
  4. auto_ptr(被 C++11 弃用)
  • Class shared_ptr 实现共享式拥有(shared ownership)概念。多个智能指针指向相同对象,该对象和其相关资源会在 “最后一个 reference 被销毁” 时被释放。为了在结构较复杂的情景中执行上述工作,标准库提供 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等辅助类。
  • Class unique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。你可以移交拥有权。它对于避免内存泄漏(resource leak)——如 new 后忘记 delete ——特别有用。

shared_ptr

  • 共享资源所有权的指针。

多个智能指针可以共享同一个对象,对象的最末一个拥有着有责任销毁对象,并清理与该对象相关的所有资源。

  • 支持定制型删除器(custom deleter),可防范 Cross-DLL 问题(对象在动态链接库(DLL)中被 new 创建,却在另一个 DLL 内被 delete 销毁)、自动解除互斥锁

weak_ptr

  • 共享资源的观察者,需要和 std::shared_ptr 一起使用,不影响资源的生命周期。

weak_ptr 允许你共享但不拥有某对象,一旦最末一个拥有该对象的智能指针失去了所有权,任何 weak_ptr 都会自动成空(empty)。因此,在 default 和 copy 构造函数之外,weak_ptr 只提供 “接受一个 shared_ptr” 的构造函数。

  • 可打破环状引用(cycles of references,两个其实已经没有被使用的对象彼此互指,使之看似还在 “被使用” 的状态)的问题

unique_ptr

  • 独占资源所有权的指针。

unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮助避免资源泄漏的智能指针。采用独占式拥有,意味着可以确保一个对象和其相应的资源同一时间只被一个 pointer 拥有。一旦拥有着被销毁或编程 empty,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。

  • unique_ptr 用于取代 auto_ptr

auto_ptr

被 c++11 弃用,原因是缺乏语言特性如 “针对构造和赋值” 的 std::move 语义,以及其他瑕疵。

auto_ptr 与 unique_ptr 比较

  • auto_ptr 可以赋值拷贝,复制拷贝后所有权转移;unqiue_ptr 无拷贝赋值语义,但实现了move 语义;
  • auto_ptr 对象不能管理数组(析构调用 delete),unique_ptr 可以管理数组(析构调用 delete[] );

补充

  • Aliasing constructor

    简单说就是构造出来的 shared_ptr 对象和参数 r 指向同一个控制块(会影响 r 指向的资源的生命周期),但是指向共享资源的指针是参数 ptr。看下面这个例子。

// shared_ptr constructor example
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

using Vec = std::vector<int>;
std::shared_ptr<int> GetSPtr() {
    auto elts = {0, 1, 2, 3, 4};
    std::shared_ptr<Vec> pvec = std::make_shared<Vec>(elts); //use_count == 1
    std::shared_ptr<int> t(pvec, &(*pvec)[2]);  //use_count == 2
    pvec.reset(); // use_count == 1
    return t;
}

int main() {

    std::shared_ptr<int> sptr = GetSPtr();// use_count == 1 ,t,pvec都销毁,sptr引用
    sptr.reset();// use_count == 1

    cout<<*sptr.get()<<endl;  // =2  指向的是&(*pvec)[2],并且延长了pvec指向vector<int>的生命周期


    return 0;
}